import json
import tempfile
from pathlib import Path

import requests, base64, time, uuid, urllib.parse as up, hmac, hashlib, os

# ---------- 全局配置 ----------
from pydub import AudioSegment

AK_ID = 'LTAI5tJy1axoohNuyDZDVdi3'  # 确保已 export / set
AK_SK = 'KMC6Ebvn0SyUc3WFGuJbnPLaiveezh'
APPKEY = "pSFKK0QHT7mHAXyq"
BIZ_API = "https://example.com/api/v1/message"
IMEI = "861265062516825"


# ---------- 百分号编码 & 签名 ----------
def percent_encode(val) -> str:
    """无论传入 bytes / int / None 统统先转成 str，再 quote"""
    if isinstance(val, bytes):
        val = val.decode()
    return up.quote(str(val), safe='~')  # RFC 3986 要求 '


def sign(params: dict, access_key_secret: str) -> str:
    """阿里云 HMAC-SHA1 GET 签名"""
    canon_qs = "&".join(
        f"{percent_encode(k)}={percent_encode(v)}"
        for k, v in sorted(params.items())
    )
    string_to_sign = f"GET&%2F&{percent_encode(canon_qs)}"
    digest = hmac.new(
        (access_key_secret + "&").encode(),
        string_to_sign.encode(),
        hashlib.sha1
    ).digest()
    return base64.b64encode(digest).decode()


# ---------- 1. 获取 NLS Token ----------
def get_token() -> str:
    params = {
        "Action": "CreateToken",
        "Version": "2019-02-28",
        "Format": "JSON",
        "AccessKeyId": AK_ID,
        "SignatureMethod": "HMAC-SHA1",
        "SignatureVersion": "1.0",
        "SignatureNonce": str(uuid.uuid4()),
        "Timestamp": time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()),
        "RegionId": "cn-shanghai",
    }
    params["Signature"] = sign(params, AK_SK)  # ← 记得把 AK_SK 传进来
    url = "https://nls-meta.cn-shanghai.aliyuncs.com/?" + up.urlencode(params)
    resp = requests.get(url, timeout=10)
    resp.raise_for_status()
    data = resp.json()
    return data["Token"]["Id"]


# ---------- 2. 文字 → AMR(Base64) ----------
def tts(text: str, token: str, voice: str = None) -> str:
    qs = {
        "appkey": APPKEY,
        "token": token,
        "text": text,
        "format": "MP3",
        "sample_rate": 8000,
        "voice": "xiaoyan"
    }
    if voice:
        qs["voice"] = voice
    r = requests.post(
        url='https://nls-gateway-cn-shanghai.aliyuncs.com/stream/v1/tts',
        headers={"Content-Type": "application/json"},
        data=json.dumps(qs),
        timeout=10  #
    )
    r.raise_for_status()
    return r.content


# ---------- 3. 发送到你的业务接口 ----------
def push(text: str):
    audio_b64 = tts(text, get_token())
    payload = {"imei": IMEI, "content": audio_b64, "type": 0}
    r = requests.post(BIZ_API, json=payload, timeout=10)
    r.raise_for_status()
    print(r.json())


def mp3_to_amr_b64(mp3: bytes) -> str:
    """
    把中文等文本 → TTS(MP3) → AMR → Base64 字符串
    返回: base64 str，可直接放进 JSON
    """
    # 用临时目录存中间文件，自动清理
    with tempfile.TemporaryDirectory() as tmpdir:
        mp3_path = os.path.join(tmpdir, "speech.mp3")
        amr_path = os.path.join(tmpdir, "speech.amr")

        # 1. 文本 → MP3
        # 把传入的mp3写入临时文件
        with open(mp3_path, "wb") as f:
            f.write(mp3)
        # 2. MP3 → AMR  (8000 Hz, 单声道，AMR-NB)
        #    pydub 底层调用 ffmpeg 来转码
        AudioSegment.from_file(mp3_path, format="mp3") \
            .export(amr_path, format="amr", parameters=[
            "-ar", "8000",  # 采样率
            "-ac", "1",  # 单声道
            "-ab", "12.2k"  # 比特率
        ])

        # 3. 读 AMR → Base64
        with open(amr_path, "rb") as f:
            return base64.b64encode(f.read()).decode()


def string_to_b64_via_tmp(text: str) -> str:
    """
    把字符串写入临时文本文件 → 读取字节 → Base64 编码
    函数返回 Base64 字符串；临时文件会在函数结束时被系统删除
    """
    # delete=False 方便我们在 with 块里重复打开文件；最后手动 unlink
    with tempfile.NamedTemporaryFile(mode="w+", encoding="utf-8", delete=False) as tmp:
        tmp.write(text)  # ① 写入明文
        tmp.flush()  # 刷盘，确保内容写完

        tmp.seek(0)  # 指针回到文件开头
        raw_bytes = tmp.read().encode("utf-8")  # ② 读取字节

    # ③ 转 Base64
    b64_str = base64.b64encode(raw_bytes).decode("ascii")

    # ④ 删除临时文件
    import os
    os.unlink(tmp.name)

    return b64_str


def send_asr(amr_bytes: bytes):
    token = get_token()
    return aliyun_asr_amr(amr_bytes, APPKEY, token)


def aliyun_asr_amr(amr_bytes: bytes, appkey: str, token: str) -> str:
    url = "https://nls-gateway-cn-shanghai.aliyuncs.com/stream/v1/asr"
    params = {
        "appkey": appkey,
        "format": "amr",  # 直接声明 AMR
        "sample_rate": 8000,  # AMR-NB 普遍是 8 kHz；若确定是 AMR-WB 改 16000
        "enable_punctuation_prediction": "true",
        "enable_inverse_text_normalization": "true"
    }
    headers = {
        "X-NLS-Token": token,
        "Content-Type": "application/octet-stream",
        "Content-Length": str(len(amr_bytes))
    }
    r = requests.post(url, params=params, headers=headers, data=amr_bytes, timeout=30)
    r.raise_for_status()
    body = r.json()
    if body["status"] == 20000000:
        return body["result"]
    raise RuntimeError(f"ASR failed: {body}")
